import * as THREE from 'plug/threejs/three.module';
import * as TWEEN from "@tweenjs/tween.js"
import {DragControls} from "plug/threejs/controls/DragControls";
import {MTLLoader} from "plug/threejs/loaders/MTLLoader";
import {OBJLoader} from "plug/threejs/loaders/OBJLoader";
import {OrbitControls} from "plug/threejs/controls/OrbitControls";
import {EventBus} from "assets/js/experiment/ex1/eventBus";


// canvas 容器
let container;
// three 组件
let camera, scene, renderer;
let controls, group;
let objects = [];
let planeArr = [];
let width = (1550 / 1918 * window.innerWidth).toFixed(0);
let height = (850 / 977 * window.innerHeight).toFixed(0);
let fov = 75;
let near = 1;
let far = 5000;
let Line = [];
let mouseVector = new THREE.Vector2(), selectObject, raycaster1 = new THREE.Raycaster();
let No = 0;//用来表示被选中飞机的编号，0表示进行过clearDiv操作而其他的正数表示选中飞机的编号
let dragcontrols, orbitcontrols;

let planePosition = []

let tweenObject = []
let tweenPlane = []

let lastTime = new Date().getTime();
let moveTime = 1000;
let __this;
let safeDistance, anime
let run = true;

export function destroy() {
  run = false;
  TWEEN.removeAll()
}

export function AnimePlay(_this) {
  run = true;
  objects = [];
  planeArr = [];
  fov = 75;
  near = 1;
  far = 5000;
  Line = [];
  mouseVector = new THREE.Vector2()
  raycaster1 = new THREE.Raycaster();
  No = 0;//用来表示被选中飞机的编号，0表示进行过clearDiv操作而其他的正数表示选中飞机的编号
  tweenObject = []
  tweenPlane = []
  lastTime = new Date().getTime();
  __this = _this
  safeDistance = _this.safe;//安全距离
  anime = document.getElementById('anime_ex1')

  init();


}

function init() {
  // 获取div
  container = anime;
  // 创建相机
  // Fov – 相机的视锥体的垂直视野角
  // Aspect – 相机视锥体的长宽比
  // Near – 相机视锥体的近平面
  // Far – 相机视锥体的远平面

  camera = new THREE.PerspectiveCamera(fov, width / height, near, far);

  camera.position.z = 2000;
  camera.lookAt(new THREE.Vector3(0, 0, 0));

  // 创建场景
  scene = new THREE.Scene();
  scene.background = new THREE.Color(0x1A2B47);

  scene.fog = new THREE.Fog(0xcce0ff, 500, 10000);

  scene.add(new THREE.AmbientLight(0x666666));

  // 添加灯光
  let light = new THREE.DirectionalLight(0xdfebff, 1);
  light.position.set(50, 200, 100);
  light.position.multiplyScalar(1.3);

  light.castShadow = true;

  light.shadow.mapSize.width = 1024;
  light.shadow.mapSize.height = 1024;

  let d = 1024;

  light.shadow.camera.left = -d;
  light.shadow.camera.right = d;
  light.shadow.camera.top = d;
  light.shadow.camera.bottom = -d;

  light.shadow.camera.far = 1000;

  scene.add(light);


  // add group
  group = new THREE.Group();
  scene.add(group);

  let onProgress = function (xhr) {
    if (xhr.lengthComputable) {
      if (xhr.loaded === xhr.total) {
        __this.loading.close()
      }
    }
  };

  let onError = function () {
  };

  let manager = new THREE.LoadingManager();
  let mtl = new MTLLoader(manager)
    .load('http://cdn.hsueh.club/plane.mtl', function (materials) {
      materials.preload();
      new OBJLoader(manager)
        .setMaterials(materials)
        .load('http://cdn.hsueh.club/plane.obj', function (object) {
          myloadplane(object);
        }, onProgress, onError);
    });

}

function myloadplane(object) {
  let geometry = new THREE.BoxGeometry(180, 80, 80);
  let material = new THREE.MeshBasicMaterial({
    color: 0xcce0ff,
    transparent: true,
    opacity: 0.01,
    side: THREE.DoubleSide
  });
  let outerMesh = new THREE.Mesh(geometry, material);
  for (let i = 1; i <= __this.planenum; i++) {
    tweenObject.push(0)
    tweenPlane.push(0)
    let ob = object.clone();
    ob.position.x = __this.planeArr[i - 1].x;
    ob.position.y = __this.planeArr[i - 1].y;
    ob.position.z = __this.planeArr[i - 1].z;
    ob.castShadow = true;
    ob.receiveShadow = true;
    scene.add(ob);
    planeArr.push(ob);

    let om = outerMesh.clone();
    om.position.x = ob.position.x;
    om.position.y = ob.position.y;
    om.position.z = ob.position.z;
    om.castShadow = true;
    om.receiveShadow = true;
    om.name = 'pl' + i;
    scene.add(om);
    objects.push(om);
  }
  initdrawline();
  renderer = new THREE.WebGLRenderer({antialias: true});
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.setSize(width, height);

  renderer.shadowMap.enabled = true;
  renderer.shadowMap.type = THREE.PCFShadowMap;
  container.appendChild(renderer.domElement);
  controls = new DragControls([...objects], camera, renderer.domElement);
  controls.addEventListener('drag', myrender);
  controls.addEventListener('dragend', render);
  initDragControl();
  initOrbitControl();

  anime.addEventListener('dblclick', dblclick, false);
  anime.addEventListener('mousewheel', mousewheel, true);
  render();
  animate();
}

//拖拽控制器
function initDragControl() {
  dragcontrols = new DragControls([...objects], camera, renderer.domElement);
  dragcontrols.addEventListener('drag', myrender);
  dragcontrols.addEventListener('dragend', (event) => {
    renderer.render(scene, camera);
    orbitcontrols.enabled = true;
  })
}

//轨迹控制器
function initOrbitControl() {
  orbitcontrols = new OrbitControls(camera, renderer.domElement);
  orbitcontrols.enabled = true;
  camera.position.set(0, 200, 2000);
  orbitcontrols.enableDamping = true;
  //是否可以缩放
  orbitcontrols.enableZoom = true;
  //是否自动旋转
  orbitcontrols.autoRotate = false;
  //设置相机距离原点的最远距离
  orbitcontrols.minDistance = 1;
  //设置相机距离原点的最远距离
  orbitcontrols.maxDistance = 3000;

  orbitcontrols.update();
}

function myrender(event) {
  orbitcontrols.enabled = false;
  let name = event.object.name; // event.object即为外部模型，在这里可以通过外层模型的name属性找到内部模型
  let tmpPlaneArr = __this.planeArr
  if ("pl" === name.substring(0, 2)) {
    let x = event.object.position.x;
    let y = event.object.position.y;
    let z = event.object.position.z;
    let num = parseInt(name.substring(2));
    x = parseInt(x);
    y = parseInt(y);
    z = parseInt(z);
    __this.choose_num = num;
    __this.plane_x = x;
    __this.plane_y = y;
    __this.plane_z = z;
    planeArr[num - 1].position.x = x;
    planeArr[num - 1].position.y = y;
    planeArr[num - 1].position.z = z;
    tmpPlaneArr[num - 1].x = x;
    tmpPlaneArr[num - 1].y = y;
    tmpPlaneArr[num - 1].z = z;
    initdrawline();
    //对于安全距离的处理
    SafeDistance(num);
  }
  __this.planeArr = tmpPlaneArr
  renderer.render(scene, camera);
}

// 鼠标滚动
function mousewheel(e) {
  let a;//来记录No

  e.preventDefault();
  if (e.wheelDelta) {  //判断浏览器IE，谷歌滑轮事件
    if (e.wheelDelta > 0) { //当滑轮向上滚动时
      if (No !== 0) {
        a = No;
        clearDiv(No);
        No = a;
        fov -= (near < fov ? 1 : 0);
        divRender(No);
      } else {
        fov -= (near < fov ? 1 : 0);
      }
    }
    if (e.wheelDelta < 0) { //当滑轮向下滚动时
      if (No !== 0) {
        a = No;
        clearDiv(No);
        No = a;
        fov += (fov < far ? 1 : 0);
        divRender(No);
      } else {
        fov += (fov < far ? 1 : 0);
      }
    }
  } else if (e.detail) {  //Firefox滑轮事件
    if (e.detail > 0) { //当滑轮向上滚动时
      if (No !== 0) {
        a = No;
        clearDiv(No);
        No = a;
        fov -= 1;
        divRender(No);
      } else {
        fov -= 1;
      }
    }
    if (e.detail < 0) { //当滑轮向下滚动时
      if (No !== 0) {
        a = No;
        clearDiv(No);
        No = a;
        fov += 1;
        divRender(No);
      } else {
        fov += 1;
      }
    }
  }
  //改变fov值，并更新场景的渲染
  camera.fov = fov;
  camera.updateProjectionMatrix();
  render();

}

// 初始画线
function initdrawline() {
  for (let i = 0; i <= __this.planenum * (__this.planenum - 1); i++) {
    scene.remove(Line[i]);
  }
  Line.splice(0, Line.length);
  for (let i = 0; i < __this.planenum; i++) {
    for (let j = 0; j < __this.planenum; j++) {

      if (i !== j) {
        let geometry = new THREE.Geometry();
        let curve = new THREE.LineCurve3(objects[i].position, objects[j].position);
        let points = curve.getPoints(100);
        geometry.setFromPoints(points);
        let material = new THREE.LineBasicMaterial({
          color: 0x0000FF,
          transparent: true,
          opacity: 0.001,
        });
        let line = new THREE.Line(geometry, material);
        scene.add(line);
        Line.push(line);
      }
    }
  }
}

// 双击事件
function dblclick(event) {
  let intersects = getIntersects(event);
  // 获取选中最近的 Mesh 对象
  if (intersects.length !== 0 && intersects[0].object instanceof THREE.Mesh) {
    // 获取 raycaster 和所有模型相交的数组，其中的元素按照距离排序，越近的越靠前

    selectObject = intersects[0].object;
    let name = selectObject.name;
    if ("pl" === name.substring(0, 2)) {
      let num = parseInt(name.substring(2));
      //在这里进行输入框的创建
      __this.choose_num = num;
      __this.plane_x = parseInt(__this.planeArr[num - 1].x);
      __this.plane_y = parseInt(__this.planeArr[num - 1].y);
      __this.plane_z = parseInt(__this.planeArr[num - 1].z);
    }
    renderer.render(scene, camera);
  }
}

function divRender(num) {
  let distance;
  let point;
  for (let i = 0; i < __this.planenum; i++) {
    if (i !== num - 1) {
      distance = toDistance(objects[i].position, objects[num - 1].position);
      distance = parseInt(distance);
      point = new THREE.Vector3((objects[i].position.x + objects[num - 1].position.x) / 2, (objects[i].position.y + objects[num - 1].position.y) / 2, (objects[i].position.z + objects[num - 1].position.z) / 2);
      let position = point;
      let windowPosition = transPosition(position);
      let left = windowPosition.x;
      let top = windowPosition.y;

      let newDiv = document.createElement("div");
      newDiv.id = "c" + i;
      newDiv.innerHTML = distance;
      newDiv.style.position = 'absolute';
      newDiv.style.left = left + 10 + 'px';
      newDiv.style.top = top + 80 + 'px';
      document.getElementById("tap").appendChild(newDiv);
      $("#tap").css("color", "#fff");
      $("#tap").css("font-weight", "bold");
      $("#tap").css("font-size", "5px");
    }
  }
}

function clearDiv(num) {
  for (let i = 0; i < __this.planenum; i++) {
    if (i !== num - 1) {
      document.getElementById('c' + i).remove();
    }
  }
}

function SafeDistance(num) {
  let a = [];//来记录如果接近安全距离的i的值
  let b = [];//来记录如果接近安全距离的j的值
  let count = 0;
  let distance;

  for (let i = 0; i <= __this.planenum * (__this.planenum - 1); i++) {
    scene.remove(Line[i]);
  }
  Line.splice(0, Line.length);

  for (let i = 0; i <= __this.planenum - 1; i++) {
    if (i !== num - 1) {
      distance = toDistance(objects[i].position, objects[num - 1].position);
      if (distance < safeDistance) {
        a.push(num - 1);
        b.push(i);
        count += 1;
      }
    }

  }

  count = 0;

  for (let i = 0; i <= __this.planenum - 1; i++) {
    for (let j = 0; j <= __this.planenum - 1; j++) {

      if (i !== j) {
        if (i === a[count] && j === b[count]) {
          let lineGeometry = new THREE.Geometry();//生成几何体
          lineGeometry.vertices.push(objects[i].position);//线段的两个顶点
          lineGeometry.vertices.push(objects[j].position);

          let line = new THREE.Line(lineGeometry, new THREE.LineDashedMaterial({
            color: 0xDC143C,//线段的颜色
            dashSize: 20,//短划线的大小
            gapSize: 5, //短划线之间的距离
            transparent: true,
            opacity: 0.5,
          }));

          line.linewidth = 100
          line.computeLineDistances();//不可或缺的，若无，则线段不能显示为虚线
          scene.add(line);
          Line.push(line);
          count += 1;
        } else {
          let lineGeometry = new THREE.Geometry();//生成几何体
          lineGeometry.vertices.push(objects[i].position);//线段的两个顶点
          lineGeometry.vertices.push(objects[j].position);
          let line = new THREE.Line(lineGeometry, new THREE.LineDashedMaterial({
            color: 0xDC143C,//线段的颜色
            dashSize: 20,//短划线的大小
            gapSize: 5, //短划线之间的距离
            transparent: true,
            opacity: 0.001,
          }));
          line.linewidth = 100
          line.computeLineDistances();//不可或缺的，若无，则线段不能显示为虚线
          scene.add(line);
          Line.push(line);
        }
      }
    }
  }
}

function transPosition(position) {
  let world_vector = new THREE.Vector3(position.x, position.y, position.z);
  let vector = world_vector.project(camera);
  let halfWidth = width / 2,
    halfHeight = height / 2;
  return {
    x: Math.round(vector.x * halfWidth + halfWidth),
    y: Math.round(-vector.y * halfHeight + halfHeight)
  };
}

function getIntersects(event) {
  event.preventDefault();


  // 通过鼠标点击位置,计算出 raycaster 所需点的位置,以屏幕为中心点,范围 -1 到 1
  let getBoundingClientRect = container.getBoundingClientRect()
  mouseVector.x = ((event.clientX - getBoundingClientRect.left) / container.offsetWidth) * 2 - 1;
  mouseVector.y = -((event.clientY - getBoundingClientRect.top) / container.offsetHeight) * 2 + 1;

  //通过鼠标点击的位置(二维坐标)和当前相机的矩阵计算出射线位置
  raycaster1.setFromCamera(mouseVector, camera);

  // 获取与射线相交的对象数组，其中的元素按照距离排序，越近的越靠前
  //返回选中的对象
  return raycaster1.intersectObjects(objects);
}

function toDistance(p1, p2) {
  return p1.distanceTo(p2);
}

function render() {
  renderer.render(scene, camera);
}

// 普通更新
function animate() {
  if (run === false) return
  requestAnimationFrame(animate);
  render();
}

export function clickPosChange(_this) {
  move(_this.planeArr)
}

function move(next_position) {
  for (let i = 0; i < planeArr.length; ++i) {
    tweenObject[i] = new TWEEN.Tween(objects[i].position).to({
      x: next_position[i].x,
      y: next_position[i].y,
      z: next_position[i].z
    }, moveTime)
    tweenPlane[i] = new TWEEN.Tween(planeArr[i].position).to({
      x: next_position[i].x,
      y: next_position[i].y,
      z: next_position[i].z
    }, moveTime)
    tweenObject[i].start()
    tweenPlane[i].start()
  }
  lastTime = new Date().getTime();
  moveAnimate()
}

function moveAnimate() {
  moveRender()
  let nowTime = new Date().getTime();
  if (nowTime - lastTime < moveTime) {
    if (run === false) return
    requestAnimationFrame(moveAnimate)
  } else {
    TWEEN.removeAll()
  }
}

function moveRender() {
  TWEEN.update();
}
